#
#2008 Julka Lipkova
#

import pygtk
pygtk.require('2.0')
import gtk
import gobject

import config

class MyDrawingArea ( gtk.EventBox ):
    def __init__(self, capture = True):
        gtk.EventBox.__init__( self )
        self.capture = capture
        self.capturing = False
        self.lineHeight = config.DEFAULT_GLYPH_HEIGHT
        self.baseLineY = ( config.DEFAULT_DAREA_HEIGHT - self.lineHeight ) / 2 + self.lineHeight
        self.bgList = []
        self.source_id = None
        self.set_size_request( config.DEFAULT_DAREA_WIDTH, config.DEFAULT_DAREA_HEIGHT )
        self.dArea = gtk.DrawingArea()
#       self.add(gtk.Button('Ahoj'))
        self.add(self.dArea)
        self.connect('motion_notify_event', self.on_motion_notify)
        self.connect('button_press_event', self.on_button_press)
        self.connect('button_release_event', self.on_button_release)
        self.dArea.connect('expose_event', self.on_expose)
        self.start_scribble()

    def finish_stroke(self, event):
#        self.line = []    //not necessary
        self.capturing = False
        self.lastEventTime = event.get_time()
        self.source_id = gobject.timeout_add( 1000, self.finish_scribble )
    
    def start_stroke(self, point = None):
        if ( self.source_id is not None ):
            gobject.source_remove(self.source_id)
            self.source_id = None
        self.line = []
        self.lineList.append( self.line )
        self.capturing = True
        if ( point is not None and self.capture and self.capturing ):
            self.add_point( point )

    def start_scribble(self):
        if ( self.source_id is not None ):
            gobject.source_remove(self.source_id)
            self.source_id = None
        self.lineList = []

    def finish_scribble(self):
        print 'Finishing scribble'
        self.emit( 'scribble_finished' );

    def add_point(self, point):
        x,y = point
#        print "Adding point %d %d" % ( x, y - self.baseLineY )
        self.line.append( ( x, y - self.baseLineY ) )
        self.dArea_paint( None, False );

#   def is_new_scribble(self, event):
#       time_dif = event.get_time() - self.last_event
#       if (time_dif > self.stroke_interval_threshold):
#           return True
#       #Events are at least 50ms and 40 pixel apart
#       elif (time_dif > 50) and (event.x_root - self.last_x)**2 + \
#                                (event.y_root - self.last_y)**2 > 1600:
#           return True
#       return False

    def addBg(self, bg):
        if (bg not in self.bgList):
            self.bgList.append( bg )
    
    def removeBg(self, bg):
        if (bg in self.bgList):
            self.bgList.remove( bg )

    def setGlyphHeight(self, height):
        self.lineHeight = height
        self.baseLineY = ( config.DEFAULT_DAREA_HEIGHT - self.lineHeight ) / 2 + self.lineHeight
        self.dArea_paint( None, True )

    def clear(self):
        self.start_scribble()
        self.dArea_paint(None, True)

    def on_motion_notify(self, sender, event, data = None ):
        if ( self.capture and self.capturing ):
            self.add_point( (event.x, event.y) )

    def on_button_press(self, sender, event, data = None ):
        if (not (self.left_button_changed(event)) ):
            return False
        self.start_stroke( (event.x, event.y) )
        print "Starting stroke"

    def on_button_release(self, sender, event, data = None ):
        if (not (self.left_button_changed(event)) ):
            return False
        self.finish_stroke( event )
        print "Finishing stroke"
#        self.add_point( (event.x, event.y) )

    def on_expose(self, sender, event, data = None ):
        self.dArea_paint( event, False )

    def left_button_changed(self, event):
        if (event.button==1):
            return True
        return False

    def dArea_paint(self, event, clear):
        #
        # event != None -> repaint in event's area
        # event == None && clear == false -> paint the last point
        # event == None && clear == true -> repaint everything
        #
        window = self.dArea.window

        allocation = self.dArea.get_allocation()
        width = allocation.width
        height = allocation.height

        cr = window.cairo_create()

        # Restrict Cairo to the exposed area; avoid extra work
        if (event is not None):
            cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
            cr.clip()
        
        # simple background
        if (event is not None or clear == True):
            cr.save()
            cr.rectangle(0, 0, width, height)
            cr.set_source_rgba( 1.0, 1.0, 1.0, 1.0 )
            cr.fill()
            cr.restore()

        # drawing backgrounds
        
        if (event is not None or clear == True):
            for bg in self.bgList:
                cr.save()
                bg.on_expose( event, cr, self )
                cr.restore()

        # scribble drawing
        cr.set_source_rgba( 0, 0, 0, 1)
        if (len(self.lineList)>0):
            cr.translate( 0, self.baseLineY )
            if (event is not None or clear == True):
                for l in self.lineList:
                    # line with more points
                    if (len(l)>1):
                        cr.set_line_width(1)
                        cr.move_to(l[0][0], l[0][1])
                        for x,y in l[1:]:
                            cr.line_to(x, y)
                        cr.stroke()
                    # only one point line
                    elif (len(l)==1):
                        x,y = l[0]
                        # TODO PI
                        cr.arc(x, y, 0.8, 0.0, 2.0 * 3.14)
                        cr.set_line_width(0)
                        cr.fill()
            # last point drawing
            else :
                l = self.lineList[-1]
                if (len(l)>1):
                    x2,y2 = l[-2]
                    x1,y1 = l[-1]
                    cr.set_line_width(1)
                    cr.move_to(x2, y2)
                    cr.line_to(x1, y1)
                    cr.stroke()
                elif (len(l) == 1):
                    x,y = l[0]
                    # TODO PI
                    cr.arc(x, y, 0.8, 0.0, 2.0 * 3.14)
                    cr.set_line_width(0)
                    cr.fill()


gobject.signal_new( 'scribble_finished', MyDrawingArea,
        gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () )

# vim: set ts=4 sw=4 sts=4 et :

